<template>
<div>
<div id="app">
<ul @dragstart="onDragStart" @dragover="onDragOver" @dragend="onDragEnd" ref="parentNode">
<li v-for="(item, index) in data" :key="index" class="item" draggable="true">{{ item }}</li>
</ul>
</div>
</div>
</template>
<script>
export default {
data () {
return {
data: [1, 2, 3, 4, 5, 6],
draging: null, // 被拖拽的对象
target: null // 目标对象
}
},
mounted () {
// 为了防止火狐浏览器拖拽的时候以新标签打开，此代码真实有效
document.body.ondrop = function (event) {
event.preventDefault()
event.stopPropagation()
}
},
methods: {
onDragStart (event) {
this.draging = event.target
},
onDragOver (event) {
this.target = event.target
const targetTop = event.target.getBoundingClientRect().top
const dragingTop = this.draging.getBoundingClientRect().top
if (this.target.nodeName === 'LI' && this.target !== this.draging) {
if (this.target) {
if (this.target.animated) {
return
}
}
 if (this._index(this.draging) < this._index(this.target)) {
      this.target.parentNode.insertBefore(this.draging, this.target.nextSibling)
    } else {
      this.target.parentNode.insertBefore(this.draging, this.target)
    }
    this._anim(targetTop, this.target)
    this._anim(dragingTop, this.draging)
  }
},
onDragEnd (event) {
  const currentNodes = Array.from(this.$refs.parentNode.childNodes)

  const data = currentNodes.map((i, index) => {
    const item = this.data.find((c) => c === i.innerText)
    return item
  })
  console.log(data)
},
_anim (startPos, dom) {
  const offset = startPos - dom.getBoundingClientRect().top
  dom.style.transition = 'none'
  dom.style.transform = `translateY(${offset}px)`

  // 触发重绘
  // eslint模式下必须添加下面这行注释
  // eslint-disable-next-line no-unused-expressions
  dom.offsetWidth
  dom.style.transition = 'transform .3s'
  dom.style.transform = ``
  // 触发重绘
  // setTimeout(()=>{
  //     dom.style.transition="transform .3s";
  //     dom.style.transform=``;
  // },0)
  clearTimeout(dom.animated)

  dom.animated = setTimeout(() => {
    dom.style.transition = ''
    dom.style.transform = ``
    dom.animated = false
  }, 300)
},

_index (el) {
  const domData = Array.from(this.$refs.parentNode.childNodes)
  return domData.findIndex((i) => i.innerText === el.innerText)
}

}
}
</script>
<style scoped>
ul {
list-style: none;
padding-bottom: 20px;
}
.item {
cursor: pointer;
/* height: 30px;
line-height: 30px; */
padding: 10px 0;
background-color: rgb(139, 36, 36);
border: 1px solid #d9d9d9;
border-radius: 4px;
color: #fff;
font-size: 30px;
padding: 10px;
}
</style>
